home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 136_01.zip / CMAZE.C < prev    next >
Text File  |  1993-06-01  |  17KB  |  973 lines

  1. /*    HEADER:  CUG136.19;
  2.     TITLE:        CMAZE;
  3.     VERSION:    1.00;
  4.     DATE:        5/29/1984;
  5.     DESCRIPTION:    "3-D Maze Game";
  6.     KEYWORDS:    game,maze;
  7.     SYSTEM:        CP/M;
  8.     FILENAME:    CMAZE.C;
  9.     AUTHORS:    R. Rodman;
  10.     COMPILERS:    C/80;
  11. */
  12.  
  13. /*        >< CMAZE by R. Rodman ><
  14.  
  15.     5/6/81 v0.8
  16.     9/14/81 v0.9 (Basic-E)
  17.     1/15/82 back to MBASIC
  18.     840512 convert to c
  19.     840513, 840514, 840515, 840516, 840518 rr continue conversion
  20.     840529 fix boxes 1.00
  21.  
  22.     Robots move crudely.
  23.     Find objects in boxes:  Compass - Radio - etc.
  24.     Shoot algorithm could show an alternating / \ or something.
  25.     Solving maze is difficult and gets boring.  Tools would help. */
  26.  
  27. #define MX 15           /* define maximum X dimension of maze */
  28. #define MY 10        /* define maximum Y dimension of maze */
  29. #define MXMY 150    /* product of mx and my */
  30.  
  31. #define CLRSCN "\033+"
  32. #define REVVID "\033G4"
  33. #define NORVID "\033G0"
  34. #define CURBEG "\033="
  35. #define CLREOS "\033Y"
  36. #define CUROFF "\033.0"
  37. #define CURON "\033.2"
  38.  
  39.     int maze[ MX ][ MY ];
  40.  
  41.     int rx[ 4 ], ry[ 4 ];
  42.     char *robot[ 4 ][ 9 ] = {
  43.         "  _______",
  44.         " / o' `o \\",
  45.         " \\ ----- /",        /* close robot, height 9 */
  46.         "  [TTTTT]",
  47.         " /[=====]\\",
  48.         "/ [MMMMM] \\",
  49.         ") [=====] (",
  50.         " / \\   / \\",
  51.         "/   \\ /   \\",
  52.  
  53.         " _____",
  54.         "/ o o \\",
  55.         "\\ --- /",
  56.         "/[TTT]\\",        /* height 7 */
  57.         ")[===](",
  58.         " [===]",
  59.         "/ \\ / \\", "", "",
  60.  
  61.         " ____",
  62.         "< o_o>",
  63.         "/[TT]\\",
  64.         " [==]",        /* height 5 */
  65.         "/ \\/ \\", "", "", "", "",
  66.  
  67.         "<oo>",
  68.         "/[]\\",        /* dist 4, height 3 */
  69.         "/\\/\\", "", "", "", "", "", ""
  70.     };
  71.  
  72.     int boxx[ 4 ], boxy[ 4 ];
  73.     char *boxes[ 3 ][ 3 ] = {
  74.         " ____",
  75.         "|\\ ___\\",
  76.         " \\|____|",
  77.  
  78.         " __",
  79.         "<__>", "",
  80.  
  81.         "<>", "", "" 
  82.     };
  83.  
  84.     int seed;
  85.  
  86.     int plyr_x, plyr_y, plyr_face;        /* player x, y, direction */
  87.  
  88.     int alive;        /* nonzero while alive */
  89.     int won;        /* won game */
  90.  
  91.     int comp, radi, shots;
  92.  
  93.     int repaint;        /* nonzero to cause repaint */
  94.  
  95. /* main program */
  96.  
  97. main()
  98. {
  99.     instructions();        /* print instructions */
  100.  
  101.     randomize();            /* randomize seed */
  102.     generate();        /* generate maze */
  103.  
  104.     init_robots();
  105.     init_boxes();
  106.  
  107.     plyr_face = 2;            /* face to "east" */
  108.  
  109.     alive = 1;
  110.     repaint = 1;
  111.     won = 0;
  112.     
  113.     while( alive && ! won ) {
  114.         if( repaint ) {
  115.             depict();
  116.             ck_boxes();
  117.             repaint = 0;
  118.         }
  119.         ck_instruments();
  120.         if( ck_robots()) alive = 0;
  121.             else {
  122.             get_command();
  123.             update_robots();
  124.         }
  125.     }
  126.     sound( ",,,,,,,,,,,,,,,," );    /* shut up */
  127.     puts( CURON );
  128. }
  129.  
  130. /* return random number between 0 and n-1 */
  131.  
  132. fnr( n )
  133. int n;
  134. {
  135.     return ( rnd() % n );
  136. }
  137.  
  138. int rnd()
  139. {
  140.     seed = seed * 3;
  141.     if( seed > 10000 ) seed = seed / 4;
  142.     return seed;
  143. }
  144.  
  145. randomize()
  146. {
  147.     int i;
  148.     seed = 1;
  149.     puts( "<Press a key>" );
  150.     while( bdos( 6, 0xFF ) == 0 ) i = rnd();
  151. }
  152.  
  153. goxy( x, y )
  154. int x, y;
  155. {
  156.     puts( CURBEG );
  157.     putchar( y + 32 );
  158.     putchar( x + 32 );
  159. }
  160.  
  161. /* print instructions */
  162.  
  163. instructions()
  164. {
  165.     puts( CLRSCN );
  166.     puts( "\t\t\t> > > A M A Z E ! < < <\n\n" );
  167.     puts( "\nVersion 1.00\n\n" );
  168.     puts( "This program presents a Perspective Maze Display on your\n" );
  169.     puts( "terminal.  Your object is to get through this maze.\n" );
  170.     puts( "four robots in the maze which will attempt to\n" );
  171.     puts( "capture you.  You have a laser pistol to protect yourself;\n" );
  172.     puts( "the pistol can fire only 5 shots.\n\n" );
  173.     puts( "On each turn, you will be asked for a command, which must\n" );
  174.     puts( "be made up of any combination of:\n\n" );
  175.     puts( "S to step forward one square\n" );
  176.     puts( "L to turn to your left, R to turn to your right\n" );
  177.     puts( "F to fire the laser pistol\n" );
  178.     puts( "O to open a box\n\n" );
  179.     puts( "I am generating the maze now.\n" );
  180.  
  181.     sound( ",,,,,,,,,,,,,,,," );    /* turn sound off */
  182. }
  183.  
  184. /*    >< Generate Maze ><
  185.  
  186. This program uses the algorithm described by R J Bishop
  187. in his article in Byte Oct 78 P 136 */
  188.  
  189. generate()
  190. {
  191.     int x, y;
  192.     int lc, oc, wf, bx, by;
  193.     int to_bit, from_bit, tp, path;
  194.     int qu[ MXMY ][ 2 ];
  195.  
  196.     for( x = 0; x < MX; ++x )
  197.         for( y = 0; y < MY; ++y )
  198.             maze[ x ][ y ] = 0;
  199.  
  200.     lc = 0;        /* last cell in queue */
  201.     oc = 0;        /* last cell taken out of queue */
  202.     wf = 0;        /* found win path yet? */
  203.  
  204.     plyr_x = 0;
  205.     plyr_y = fnr( MY );    /* player start position */
  206.  
  207.     bx = plyr_x;
  208.     by = plyr_y;        /* random walk start position */
  209.     
  210.     x = 1; y = 1;        /* junk values to cause loop to execute */
  211.  
  212. /* loop while any valid starting points for walks are in the queue */
  213.  
  214.     while( oc <= lc ) {
  215.  
  216. /* random walk from bx, by until we come to a dead end or generate a goal. */
  217.  
  218.         x = bx;
  219.         y = by;
  220.  
  221.         while( x + y ) {
  222.  
  223. /* inner loop, try to move to another square from bx, by */
  224.  
  225.             tp = 0;        /* tried path */
  226.             while( tp < 15 ) {
  227.                 x = bx;
  228.                 y = by;
  229.                 path = fnr( 4 );    /* get random path */
  230.  
  231.                 switch( path ) {
  232.  
  233.                 case 0 :     to_bit = 1;
  234.                         from_bit = 2;
  235.                         --x;
  236.                         break;
  237.  
  238.                 case 1 :     to_bit = 2;
  239.                         from_bit = 1;
  240.                         ++x;
  241.                         break;
  242.  
  243.                 case 2 :     to_bit = 4;
  244.                         from_bit = 8;
  245.                         --y;
  246.                         break;
  247.  
  248.                 case 3 :     to_bit = 8;
  249.                         from_bit = 4;
  250.                         ++y;
  251.                         break;
  252.                 }
  253.  
  254.                 tp = tp | to_bit;
  255.  
  256. /* break out of loop if we hit an empty square */
  257.  
  258.                 if( x >= 0 && x <= ( MX - 2 )
  259.                     && y >= 0 && y < MY )
  260.                     if( maze[ x ][ y ] == 0 ) break;
  261.  
  262. /* otherwise try again */
  263.  
  264.             }
  265.  
  266. /* see if we got out, or just fell out */
  267.  
  268.             if( tp >= 15 ) {
  269.                 x = 0;        /* no path left */
  270.                 y = 0;
  271.             }
  272.  
  273. /* if not, we must have a good path here */
  274.  
  275.             if( x + y ) {
  276.  
  277. /* flag where we opened path to */
  278.  
  279.                 maze[ bx ][ by ] = maze[ bx ][ by ] | to_bit;
  280.  
  281.                 bx = x;        /* new origin */
  282.                 by = y;
  283.  
  284. /* flag where we opened path from */
  285.  
  286.                 maze[ bx ][ by ] = maze[ bx ][ by ] | from_bit;
  287.  
  288.                 qu[ lc ][ 0 ] = bx;
  289.                 qu[ lc ][ 1 ] = by;    /* save in queue */
  290.                 ++lc;
  291.  
  292. /* have we no solution yet, and are we on next to last column of maze? */
  293.  
  294.                 if( wf == 0 && bx == ( MX - 2 )) {
  295.  
  296. /* if so, generate a goal */
  297.  
  298.                     ++wf;        /* mark goal found */
  299.  
  300.                     maze[ bx ][ by ] =
  301.                         maze[ bx ][ by ] | 2;
  302.                     maze[ MX - 1 ][ by ] = 1;
  303.  
  304.                     x = 0;        /* cause no path */
  305.                     y = 0;
  306.                 }
  307.             }
  308.         }
  309.  
  310. /* no path. what do you do now? */
  311.  
  312.         if( lc == MXMY ) break;    /* give up if we've used all */
  313.  
  314.         bx = qu[ oc ][ 0 ];    /* pull next starting point */
  315.         by = qu[ oc ][ 1 ];    /* from the queue */
  316.         ++oc;
  317.     }
  318. }
  319.  
  320. init_robots()
  321. {
  322.     int i;
  323.     for( i = 0; i < 4; ++i ) {
  324.         rx[ i ] = fnr( MX - 3 ) + 1;
  325.         ry[ i ] = fnr( MY );
  326.     }
  327.  
  328.     shots = 5;
  329. }
  330.  
  331. init_boxes()
  332. {
  333.     int i;
  334.     for( i = 0; i < 4; ++i ) {
  335.         boxx[ i ] = fnr( MX - 3 ) + 1;
  336.         boxy[ i ] = fnr( MY );
  337.     }
  338.  
  339.     comp = 0;    /* you have no compass */
  340.     radi = 0;    /* you have no radio */
  341.     shots = 5;
  342. }
  343.  
  344. /* depict view from current position and location */
  345.  
  346. depict()
  347. {
  348.     int lsm, rsm;    /* left side, right side masks */
  349.     int wx, wy;    /* wall x, y */
  350.     int mw, wf, w;
  351.     int lw[ 6 ], rw[ 6 ];
  352.     char ldol, rdol, wdol[ 3 ];
  353.     int js, l1, l2, j1, j2, l, j, mi; 
  354.  
  355. /* define side masks */
  356.     
  357.     switch( plyr_face ) {
  358.  
  359.     case 1 :    lsm = 8;
  360.             rsm = 4;
  361.             break;
  362.  
  363.     case 2 :    lsm = 4;
  364.             rsm = 8;
  365.             break;
  366.  
  367.     case 4 :    lsm = 1;
  368.             rsm = 2;
  369.             break;
  370.  
  371.     case 8 :    lsm = 2;
  372.             rsm = 1;
  373.             break;
  374.     }
  375.  
  376. /* now we know which way to look */
  377.  
  378.     wx = plyr_x;
  379.     wy = plyr_y;
  380.     mw = 4;        /* max wall even if we don't run into one */
  381.     wf = 0;
  382.  
  383.     w = 0;
  384.  
  385.     while( w < mw ) {
  386.  
  387.         lw[ w ] = maze[ wx ][ wy ] & lsm;
  388.         rw[ w ] = maze[ wx ][ wy ] & rsm;
  389.  
  390. /* mw is the wall beyond which we cannot see */
  391.  
  392.         if( ! ( maze[ wx ][ wy ] & plyr_face )) {
  393.             mw = w;
  394.             lw[ w + 1 ] = 1;
  395.             rw[ w + 1 ] = 1;
  396.         }
  397.  
  398.         if( wx == MX - 1 ) wf = 1;
  399.  
  400.         switch( plyr_face ) {
  401.         case 1 :    --wx;    break;
  402.         case 2 :    ++wx;    break;
  403.         case 4 :    --wy;    break;
  404.         case 8 :    ++wy;    break;
  405.         }
  406.  
  407.         ++w;
  408.     }
  409.  
  410. /* got wall arrays, now draw them */
  411.  
  412.     puts( CLRSCN );        /* clear the screen */
  413.     puts( CUROFF );
  414.  
  415.     ldol = '\\';
  416.     rdol = '/';
  417.  
  418. /* js is 1 for top half of screen, -1 for bottom */
  419.  
  420.     for( js = 1; js >= -1; js -= 2 ) {
  421.  
  422.         if( js == 1 ) {
  423.             l1 = 0;
  424.             l2 = 4;
  425.             j1 = 0;
  426.             j2 = 1;
  427.         } else {
  428.             l1 = 4;
  429.             l2 = 0;
  430.             j1 = 1;
  431.             j2 = 0;
  432.             ldol = '/';
  433.             rdol = '\\';
  434.         }
  435.  
  436. /* l is line of screen, going 0 to 4 on top, then 4 to 0 on bottom. */
  437.  
  438.         for( l = l1; l != l2 + js; l += js ) {
  439.  
  440. /* j is used to cause two screen lines to be used for each step of l. */
  441.  
  442.             for( j = j1; j != j2 + js; j += js ) {
  443.  
  444. /* how many spaces go in the middle of line l? */
  445.  
  446.                 mi = 40 - 6 * l;
  447.  
  448. /* draw left side old walls, ie walls already passed by l. */
  449.  
  450.                 for( w = 0; w < l; ++w ) {
  451.  
  452.                     if( w > mw ) puts( "   " );
  453.                         else {
  454.  
  455.                         if(( w == l - 1 )
  456.                             && ( lw[ w ] != 0 )
  457.                             && ( j == 0 ))
  458.                             wdol[ 0 ] = '-';
  459.                             else wdol[ 0 ] = ' ';
  460.  
  461.                         wdol[ 1 ] = wdol[ 0 ];
  462.                         wdol[ 2 ] = wdol[ 1 ];
  463.  
  464.                         if(( lw[ w ] > 0 )
  465.                             && ( w != mw ))
  466.                             wdol[ 2 ] = '|';
  467.  
  468.                         if(( lw[ w ] == 0 )
  469.                             && ( lw[ w + 1 ] != 0
  470.                             ))
  471.                             wdol[ 2 ] = '|';
  472.  
  473.                         putchar( wdol[ 0 ] );
  474.                         putchar( wdol[ 1 ] );
  475.                         putchar( wdol[ 2 ] );
  476.                     }
  477.                 }
  478.  
  479. /* left side new wall */
  480.  
  481.                 switch( j ) {
  482.  
  483.                 case 0 :    if( l == ( mw + 1 )) {
  484.                             puts( "--" );
  485.                             break;
  486.                         }
  487.                         if( l > mw ) {
  488.                             puts( "  " );
  489.                             break;
  490.                         }
  491.                         if( lw[ l ] == 0 ) {
  492.                             putchar( ldol );
  493.                             putchar( ' ' );
  494.                         } else puts( "  " );
  495.  
  496.                         break;
  497.  
  498.                 case 1 :    if( l > mw ) {
  499.                             puts( "  " );
  500.                             break;
  501.                         }
  502.                         if( lw[ l ] == 0 ) {
  503.                             putchar( ' ' );
  504.                             putchar( ldol );
  505.                         } else puts( "  " );
  506.                 }
  507.  
  508.                 if(( l == ( mw + 1 )) && ( j == 0 ))
  509.                     repchr( mi, '-' );
  510.                     else repchr( mi, ' ' );
  511.  
  512. /* right side new walls */
  513.  
  514.                 switch( j ) {
  515.  
  516.                 case 0 :    if( l == ( mw + 1 )) {
  517.                             puts( "--" );
  518.                             break;
  519.                         }
  520.                         if( l > mw ) {
  521.                             puts( "  " );
  522.                             break;
  523.                         }
  524.                         if( rw[ l ] == 0 ) {
  525.                             putchar( ' ' );
  526.                             putchar( rdol );
  527.                         } else puts( "  " );
  528.  
  529.                         break;
  530.  
  531.                 case 1 :    if( l > mw ) {
  532.                             puts( "  " );
  533.                             break;
  534.                         }
  535.                         if( rw[ l ] == 0 ) {
  536.                             putchar( rdol );
  537.                             putchar( ' ' );
  538.                         } else puts( "  " );
  539.                 }
  540.  
  541. /* right side old walls */
  542.  
  543.                 for( w = l - 1; w >= 0; --w ) {
  544.  
  545.                     if( w > mw ) puts( "   " );
  546.                         else {
  547.  
  548.                         if(( w == l - 1 ) 
  549.                             && ( rw[ w ] != 0 )
  550.                             && ( j == 0 ))
  551.                             wdol[ 0 ] = '-';
  552.                             else wdol[ 0 ] = ' ';
  553.  
  554.                         wdol[ 1 ] = wdol[ 0 ];
  555.                         wdol[ 2 ] = wdol[ 1 ];
  556.  
  557.                         if(( rw[ w ] > 0 )
  558.                             && ( w != mw ))
  559.                             wdol[ 0 ] = '|';
  560.  
  561.                         if(( rw[ w ] == 0 )
  562.                             && ( rw[ w + 1 ] != 0
  563.                             ))
  564.                             wdol[ 0 ] = '|';
  565.  
  566.                         putchar( wdol[ 0 ] );
  567.                         putchar( wdol[ 1 ] );
  568.                         putchar( wdol[ 2 ] );
  569.                     }
  570.                 }
  571.  
  572.                 putchar( '\n' );
  573.  
  574.             }    /* loop on j */
  575.  
  576.         }    /* loop on l */
  577.  
  578.     }    /* loop on js (top or bottom) */
  579.  
  580.     puts( CLREOS );
  581.  
  582. /* draw exit sign */
  583.  
  584.     if( wf ) {
  585.         goxy( 18, 10 );
  586.         puts( "E X I T" );
  587.     }
  588. }
  589.  
  590. /* check for robots */
  591.  
  592. int ck_robots()
  593. {
  594.     int wx, wy, k, dr, r, d, h, w;
  595.  
  596.     wx = plyr_x;
  597.     wy = plyr_y;
  598.  
  599.     k = 0;
  600.     dr = 99;
  601.  
  602.     w = 0;
  603.  
  604. /* step forward along player's view */
  605.  
  606.     while( maze[ wx ][ wy ] & plyr_face ) {
  607.  
  608.         switch( plyr_face ) {
  609.         case 1 :    --wx;    break;
  610.         case 2 :    ++wx;    break;
  611.         case 4 :    --wy;    break;
  612.         case 8 :    ++wy;    break;
  613.         }
  614.  
  615.         for( r = 0; r < 4; ++r ) {
  616.             if( rx[ r ] == wx && ry[ r ] == wy ) {
  617.  
  618.                 for( h = 0; h < 9; ++h ) {
  619.                     goxy( 15 + w, 13 + h );
  620.                     puts( robot[ w ][ h ] );
  621.                 }
  622.             }
  623.  
  624.             if( rx[ r ] == plyr_x && ry[ r ] == plyr_y ) k = r;
  625.  
  626.             d = abs( rx[ r ] - plyr_x ) + abs( ry[ r ] - plyr_y );
  627.             if( d < dr ) dr = d;
  628.         }
  629.         ++w;    /* increment distance */
  630.     }
  631.  
  632.     if( dr < 5 ) {
  633.  
  634.         sound( "255,9,0,0,1,0,1,234" );
  635.         cricket( 8, 9 - 2 * dr );    /* make a robot sound */
  636.         cricket( 9, 9 - 2 * dr );
  637.         cricket( 10, 9 - 2 * dr );
  638.  
  639.     } else sound( ",,,,,,,,,,,,,,,," );
  640.  
  641.     if( k ) {
  642.         goxy( 50, 22 );
  643.         puts( "Aighh! The robots got you!" );
  644.     }
  645.  
  646.     return k;    /* nonzero value means you got it */
  647. }
  648.  
  649. /* check boxes */
  650.  
  651. ck_boxes()
  652. {
  653.     int wx, wy, b, d, h, w;
  654.  
  655.     wx = plyr_x;
  656.     wy = plyr_y;
  657.  
  658.     w = 0;
  659.  
  660. /* look forward along player's view */
  661.  
  662.     while( maze[ wx ][ wy ] & plyr_face ) {
  663.  
  664.         switch( plyr_face ) {
  665.         case 1 :    --wx;    break;
  666.         case 2 :    ++wx;    break;
  667.         case 4 :    --wy;    break;
  668.         case 8 :    ++wy;    break;
  669.         }
  670.  
  671.         if( w < 3 ) for( b = 0; b < 4; ++b ) {
  672.             if( boxx[ b ] == wx && boxy[ b ] == wy ) {
  673.                 d = fnr( 10 ) + 12;
  674.                 for( h = 0; h < 3; ++h ) {
  675.                     goxy( d, 16 + w * 2 + h );
  676.                     puts( boxes[ w ][ h ] );
  677.                 }
  678.             }
  679.         }
  680.         ++w;        /* increment distance */
  681.     }
  682. }
  683.  
  684. /* check the instruments */
  685.  
  686. ck_instruments()
  687. {
  688.     if( comp ) {
  689.         goxy( 50, 10 );
  690.         puts( "Compass Reading: " );
  691.  
  692.         switch( plyr_face ) {
  693.         case 1 :    puts( "WEST " );    break;
  694.         case 2 :    puts( "EAST " );    break;
  695.         case 4 :    puts( "NORTH" );    break;
  696.         case 8 :    puts( "SOUTH" );    break;
  697.         }
  698.     }
  699.  
  700.     goxy( 50, 15 );
  701.     putchar( shots + '0' );
  702.     puts( " shots remaining" );
  703. }
  704.  
  705. /* get and process user command */
  706.  
  707. get_command()
  708. {
  709.     int b;
  710.     char command;
  711.  
  712.     goxy( 0, 22 );
  713.     puts( "Command (L/R/S/F/O): " );
  714.     puts( CURON );
  715.     while( ! ( command = bdos( 6, 0xFF ))) ;
  716.     puts( CUROFF );
  717.  
  718.     switch( command ) {
  719.  
  720.     case '\003' :    exit();
  721.  
  722. /* open box */
  723.  
  724.     case 'O' :    for( b = 0; b < 4; ++b ) {
  725.                 if( boxx[ b ] == plyr_x
  726.                     && boxy[ b ] == plyr_y ) {
  727.  
  728.                     boxx[ b ] = 99;
  729.  
  730.                     goxy( 40, 22 );
  731.                     puts( "Box contains a " );
  732.                     switch( b ) {
  733.  
  734.                     case 0 :    puts( "Compass!" );
  735.                             comp = 1;
  736.                             break;
  737.                     case 1 :    puts( "Radio!" );
  738.                             radi = 1;
  739.                             break;
  740.                     case 2 :    puts( "Rubik's Cube" );
  741.                             break;
  742.                     case 3 :    puts(
  743.     "Laser Pistol recharge unit!" );
  744.                             shots += 5;
  745.                     }
  746.                 }
  747.             }
  748.             break;
  749.  
  750.     case 'F' :    fire();
  751.             break;
  752.  
  753. /* turn left */
  754.  
  755.     case 'L' :    repaint = 1;
  756.             if( plyr_face == 1 ) {
  757.                 plyr_face = 8;
  758.                 break;
  759.             }
  760.             if( plyr_face == 8 ) {
  761.                 plyr_face = 2;
  762.                 break;
  763.             }
  764.             if( plyr_face == 2 ) {
  765.                 plyr_face = 4;
  766.                 break;
  767.             }
  768.             if( plyr_face == 4 ) {
  769.                 plyr_face = 1;
  770.                 break;
  771.             }
  772.             break;
  773.  
  774. /* turn right */
  775.  
  776.     case 'R' :    repaint = 1;
  777.             if( plyr_face == 1 ) {
  778.                 plyr_face = 4;
  779.                 break;
  780.             }
  781.             if( plyr_face == 4 ) {
  782.                 plyr_face = 2;
  783.                 break;
  784.             }
  785.             if( plyr_face == 2 ) {
  786.                 plyr_face = 8;
  787.                 break;
  788.             }
  789.             if( plyr_face == 8 ) {
  790.                 plyr_face = 1;
  791.                 break;
  792.             }
  793.             break;
  794.  
  795. /* step forward */
  796.  
  797.     case 'S' :    if( maze[ plyr_x ][ plyr_y ] & plyr_face ) {
  798.  
  799.                 switch( plyr_face ) {
  800.                 case 1 :    --plyr_x;    break;
  801.                 case 2 :    ++plyr_x;    break;
  802.                 case 4 :    --plyr_y;    break;
  803.                 case 8 :    ++plyr_y;    break;
  804.                 }
  805.  
  806.                 if( plyr_x == MX - 1 ) {
  807.                     puts( "You made it!! You''ve Won!!!" );
  808.                     won = 1;
  809.                 } else repaint = 1;
  810.  
  811.             } else {
  812.                 goxy( 40, 22 );
  813.                 puts( "CAN'T!" );
  814.             }
  815.             break;
  816.     default:    putchar( '\007' );
  817.     }
  818. }
  819.  
  820. update_robots()
  821. {
  822.     int r, x, y, rd, ok;
  823.  
  824.     for( r = 0; r < 4; ++r ) {
  825.  
  826.         if( rx[ r ] != 99 ) {
  827.  
  828.             ok = 0;
  829.  
  830.             while( ! ok ) {
  831.                 x = rx[ r ];
  832.                 y = ry[ r ];
  833.  
  834.                 switch( fnr( 3 )) {
  835.  
  836.                 case 0 :    if( rx[ r ] < plyr_x ) {
  837.                             rd = 2;
  838.                             ++x;
  839.                         } else {
  840.                             rd = 1;
  841.                             --x;
  842.                         }
  843.                         break;
  844.                 case 1 :    if( ry[ r ] < plyr_y ) {
  845.                             rd = 8;
  846.                             ++y;
  847.                         } else {
  848.                             rd = 4;
  849.                             --y;
  850.                         }
  851.                         break;
  852.                 case 2 :    rd = 15;    /* no move */
  853.                 }
  854.  
  855.                 ok = maze[ rx[ r ]][ ry[ r ]] & rd;
  856.             }
  857.         }
  858.     }
  859. }
  860.  
  861. /* fire laser */
  862.  
  863. fire()
  864. {
  865.     int wx, wy, r, w, h;
  866.  
  867.     if( ! shots ) return;
  868.  
  869.     --shots;
  870.  
  871.     sound( "1,0,,,,,1,238,7,7" );
  872.  
  873.     r = 0;
  874.     for( wx = 2; wx < 56; ++wx ) cricket( r, wx );
  875.  
  876.     sound( ",,,,,,,,," );
  877.  
  878.     wx = plyr_x;
  879.     wy = plyr_y;
  880.  
  881. /* look forward along player's view */
  882.  
  883.     w = 0;
  884.  
  885.     while(( maze[ wx ][ wy ] & plyr_face ) && ( w < 4 )) {
  886.  
  887.         switch( plyr_face ) {
  888.         case 1 :    --wx;    break;
  889.         case 2 :    ++wx;    break;
  890.         case 4 :    --wy;    break;
  891.         case 8 :    ++wy;    break;
  892.         }
  893.  
  894.         goxy( 19, 18 - ( 2 * w ));
  895.         putchar( '*' );
  896.  
  897.         for( r = 0; r < 4; ++r ) {
  898.  
  899.             if( rx[ r ] == wx && ry[ r ] == wy ) {
  900.                 goxy( 50, 22 );
  901.                 puts( "\007>HIT!<" );
  902.  
  903.                 for( h = 3; h < 12; ++h ) {
  904.                     goxy( 19 + ( h / 2 ) - fnr( h ),
  905.                         12 + ( h / 2 ) - fnr( h ));
  906.                     putchar( ' ' + fnr( 16 ));
  907.                 }
  908.  
  909.                 rx[ r ] = 99;
  910.                 break;
  911.             }
  912.         }
  913.         ++w;
  914.     }
  915.     repaint = 1;
  916. }
  917.  
  918. /* generate sound effects */
  919.  
  920. sound( p )
  921. char *p;
  922. {
  923.      int r, v;
  924.     char c;
  925.  
  926.     r = 0;
  927.     v = 0;
  928.  
  929.     while( c = *p++ ) {
  930.         if( c >= '0' && c <= '9' ) {
  931.             v = 10 * v + c - '0';
  932.         } else {
  933.             cricket( r, v );    /* send out value */
  934.             v = 0;
  935.             ++r;            /* increment register */
  936.         }
  937.     }
  938. }
  939.  
  940. /* send value to cricket */
  941.  
  942. cricket( r, v )
  943. int r, v;
  944. {
  945.     portout( 177, r );
  946.     portout( 176, v );
  947. }
  948.  
  949. repchr( n, c )
  950. int n;
  951. char c;
  952. {
  953.     while( n-- ) putchar( c );
  954. }
  955.  
  956. puts( p )
  957. char *p;
  958. {
  959.     while( *p ) putchar( *p++ );
  960. }
  961.  
  962. int abs( i )
  963. int i;
  964. {
  965.     if( i < 0 ) return 0 - i;
  966.         else return i;
  967. }
  968.  
  969. #include "portio.c"
  970. #include "stdlib.c"
  971.  
  972.  
  973.